package com.hh.service.service.impl.integral;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hh.common.constants.Constants;
import com.hh.common.enums.IntegralTransactionType;
import com.hh.common.exception.HhException;
import com.hh.common.model.integral.IntegralOrder;
import com.hh.common.model.integral.IntegralOrderInfo;
import com.hh.common.model.integral.PointsMallCategory;
import com.hh.common.model.integral.PointsMallGoods;
import com.hh.common.model.product.StoreProduct;
import com.hh.common.model.product.StoreProductAttr;
import com.hh.common.model.product.StoreProductAttrValue;
import com.hh.common.model.product.StoreProductDescription;
import com.hh.common.model.user.User;
import com.hh.common.model.user.UserAddress;
import com.hh.common.page.CommonPage;
import com.hh.common.request.PageParamRequest;
import com.hh.common.request.StoreProductAttrAddRequest;
import com.hh.common.request.StoreProductAttrValueAddRequest;
import com.hh.common.request.StoreSeckillSearchRequest;
import com.hh.common.request.integral.IntegralCreateOrderRequest;
import com.hh.common.request.integral.StoreIntegralAddRequest;
import com.hh.common.response.AttrValueResponse;
import com.hh.common.response.integral.*;
import com.hh.common.utils.DateUtil;
import com.hh.common.utils.HhUtil;
import com.hh.common.vo.MyRecord;
import com.hh.common.vo.user.UserAssetVo;
import com.hh.service.dao.integral.PointsMallCategoryDao;
import com.hh.service.dao.integral.PointsMallGoodsDao;
import com.hh.service.service.*;
import com.hh.service.service.integral.*;
import com.hh.service.service.user.UserAssetService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PointsMallServiceImpl extends ServiceImpl<PointsMallGoodsDao,PointsMallGoods> implements PointsMallService {

    @Resource
    private PointsMallGoodsDao dao;

    @Resource
    private PointsMallCategoryDao pointsMallCategoryDao;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private SystemAttachmentService systemAttachmentService;

    @Autowired
    private StoreProductAttrService attrService;

    @Autowired
    private StoreProductAttrValueService storeProductAttrValueService;

    @Autowired
    private StoreProductDescriptionService storeProductDescriptionService;

    @Autowired
    private PointsMallCategoryService pointsMallCategoryService;

    @Autowired
    private StoreProductService storeProductService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserAddressService userAddressService;

    @Autowired
    private PointsMallGoodsService pointsMallGoodsService;

    @Autowired
    private StoreProductAttrValueService attrValueService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IntegralOrderService integralOrderService;

    @Autowired
    private IntegralOrderInfoService integralOrderInfoService;

    @Autowired
    private IntegralOrderStatusService integralOrderStatusService;

    @Autowired
    private UserAssetService userAssetService;

    @Override
    public Boolean saveIntegralGoods(StoreIntegralAddRequest request) {
        request.getAttrValue().forEach(e -> {
            if ((ObjectUtil.isNull(e.getQuota()) || e.getQuota() <= 0)) {
                throw new HhException("请正确输入限量");
            }
        });

        if (isExistTile(request.getTitle())) {
            throw new HhException("活动标题已经存在");
        }

        PointsMallGoods pointsMallGoods = new PointsMallGoods();
        BeanUtils.copyProperties(request, pointsMallGoods);
        // 主图
        pointsMallGoods.setImage(systemAttachmentService.clearPrefix(pointsMallGoods.getImage()));

        List<String> sliderImages = request.getSliderImages();
        String sliderImagesStr = String.join(",", sliderImages);
        // 轮播图
        pointsMallGoods.setImages(systemAttachmentService.clearPrefix(sliderImagesStr));


        //计算价格
        List<StoreProductAttrValueAddRequest> attrValueAddRequestList = request.getAttrValue();
        //计算价格
        StoreProductAttrValueAddRequest minAttrValue = attrValueAddRequestList.stream().min(Comparator.comparing(StoreProductAttrValueAddRequest::getPrice)).get();
        pointsMallGoods.setPrice(minAttrValue.getPrice().intValue());
        pointsMallGoods.setOtPrice(minAttrValue.getOtPrice());
        pointsMallGoods.setCost(minAttrValue.getCost());
        int quota = attrValueAddRequestList.stream().mapToInt(StoreProductAttrValueAddRequest::getQuota).sum();
        pointsMallGoods.setStock(quota);
        pointsMallGoods.setQuota(quota);
        pointsMallGoods.setQuotaShow(quota);
        pointsMallGoods.setSort(0);
        if (ObjectUtil.isNotNull(request.getSort())) {
            pointsMallGoods.setSort(request.getSort());
        }

        List<StoreProductAttrAddRequest> addRequestList = request.getAttr();
        List<StoreProductAttr> attrList = addRequestList.stream().map(e -> {
            StoreProductAttr attr = new StoreProductAttr();
            BeanUtils.copyProperties(e, attr);
            attr.setType(Constants.PRODUCT_TYPE_INTEGRAL);
            return attr;
        }).collect(Collectors.toList());

        List<StoreProductAttrValue> attrValueList = attrValueAddRequestList.stream().map(e -> {
            StoreProductAttrValue attrValue = new StoreProductAttrValue();
            BeanUtils.copyProperties(e, attrValue);
            attrValue.setId(null);
            attrValue.setSuk(e.getSuk());
            attrValue.setQuota(e.getQuota());
            attrValue.setQuotaShow(e.getQuota());
            attrValue.setType(Constants.PRODUCT_TYPE_INTEGRAL);
            attrValue.setImage(systemAttachmentService.clearPrefix(e.getImage()));
            return attrValue;
        }).collect(Collectors.toList());

        // 处理富文本
        StoreProductDescription spd = new StoreProductDescription();
        spd.setDescription(request.getContent().length() > 0 ? systemAttachmentService.clearPrefix(request.getContent()) : "");
        spd.setType(Constants.PRODUCT_TYPE_INTEGRAL);

        Boolean execute = transactionTemplate.execute(e -> {
            save(pointsMallGoods);

            attrList.forEach(attr -> attr.setProductId(pointsMallGoods.getId()));
            attrValueList.forEach(value -> value.setProductId(pointsMallGoods.getId()));
            attrService.saveBatch(attrList);
            storeProductAttrValueService.saveBatch(attrValueList);

            spd.setProductId(pointsMallGoods.getId());
            storeProductDescriptionService.deleteByProductId(pointsMallGoods.getId(), Constants.PRODUCT_TYPE_INTEGRAL);
            storeProductDescriptionService.save(spd);
            return Boolean.TRUE;
        });

        return execute;
    }

    @Override
    public PageInfo<StoreIntegralResponse> getList(StoreSeckillSearchRequest request, PageParamRequest pageParamRequest) {
        //带 StoreSeckill 类的多条件查询
        Page<PointsMallGoods> storeSeckillProductPage = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        LambdaQueryWrapper<PointsMallGoods> lambdaQueryWrapper = Wrappers.lambdaQuery();
        PointsMallGoods model = new PointsMallGoods();
        BeanUtils.copyProperties(request, model);
        if (null != request.getStatus()) {
            lambdaQueryWrapper.eq(PointsMallGoods::getStatus,request.getStatus());
        }
        if (StringUtils.isNotBlank(request.getKeywords())) {
            lambdaQueryWrapper.like(PointsMallGoods::getTitle,request.getKeywords())
                    .or().like(PointsMallGoods::getId,request.getKeywords());
        }

        lambdaQueryWrapper.eq(PointsMallGoods::getIsDel,false);
        lambdaQueryWrapper.orderByDesc(PointsMallGoods::getSort).orderByDesc(PointsMallGoods::getId);
        List<PointsMallGoods> storeProducts = dao.selectList(lambdaQueryWrapper);
        List<StoreIntegralResponse> storeProductResponses = new ArrayList<>();


        // 查询所有秒杀配置后根据关系添加到秒杀商品列表中

        for (PointsMallGoods product : storeProducts) {
            StoreIntegralResponse storeProductResponse = new StoreIntegralResponse();
            BeanUtils.copyProperties(product, storeProductResponse);
            storeProductResponse.setImages(HhUtil.stringToArrayStr(product.getImages()));
            storeProductResponse.setCateName(getCateName(product.getCategoryId()));
            StoreProductAttr storeProductAttrPram = new StoreProductAttr();
            //storeProductAttrPram.setProductId(product.getId()).setType(Constants.PRODUCT_TYPE_SECKILL);
            List<StoreProductAttr> attrs = attrService.getByEntity(storeProductAttrPram);

            if (attrs.size() > 0) {
                storeProductResponse.setAttr(attrs);
            }
            // 处理富文本
            StoreProductDescription sd = storeProductDescriptionService.getOne(
                    new LambdaQueryWrapper<StoreProductDescription>()
                            .eq(StoreProductDescription::getProductId, product.getId())
                            .eq(StoreProductDescription::getType, Constants.PRODUCT_TYPE_INTEGRAL));
            if (null != sd) {
                storeProductResponse.setContent(null == sd.getDescription()?"":sd.getDescription());
            }

            storeProductResponses.add(storeProductResponse);
        }
        // 多条sql查询处理分页正确
        return CommonPage.copyPageInfo(storeSeckillProductPage, storeProductResponses);
    }

    private String getCateName(Integer categoryId) {
        PointsMallCategory itemById = pointsMallCategoryService.getItemById(categoryId);
        if(ObjectUtil.isNotNull(itemById)){
            return itemById.getName();
        }
        return "";
    }

    @Override
    public List<PointsMallCategory> getPointsMallCategoryList() {
        LambdaQueryWrapper<PointsMallCategory> objectLambdaQueryWrapper = Wrappers.lambdaQuery();
        objectLambdaQueryWrapper.orderByAsc(PointsMallCategory::getSort);
        List<PointsMallCategory> pointsMallCategories = pointsMallCategoryDao.selectList(objectLambdaQueryWrapper);
        return pointsMallCategories;
    }

    @Override
    public List<StoreIntegralH5Response> getPointsMallList(Integer cateId, String keyword,PageParamRequest pageParamRequest) {
        PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<PointsMallGoods> lqw = Wrappers.lambdaQuery();
        lqw.eq(PointsMallGoods::getStatus,1);
        lqw.eq(PointsMallGoods::getIsDel,false);
        lqw.eq(PointsMallGoods::getIsShow,true);
        if(null != cateId){
            lqw.eq(PointsMallGoods::getCategoryId,cateId);
        }
        if(StrUtil.isNotBlank(keyword)){
            lqw.like(PointsMallGoods::getTitle,keyword);
        }
        lqw.orderByDesc(PointsMallGoods::getId);
        List<PointsMallGoods> storeSeckills = dao.selectList(lqw);
        if (CollUtil.isEmpty(storeSeckills)) {
            return CollUtil.newArrayList();
        }
        List<StoreIntegralH5Response> responses = new ArrayList<>();
        storeSeckills.forEach(e->{
            StoreIntegralH5Response response = new StoreIntegralH5Response();
            BeanUtils.copyProperties(e, response);
            responses.add(response);
        });
        return responses;
    }

    @Override
    public List<IntegralCateListResponse> getPointsMallCateList() {
        return pointsMallCategoryService.getList();
    }

    @Override
    public StoreIntegralDetailResponse goodsDetails(Integer id) {
        // 获取秒杀商品信息
        PointsMallGoods pointsMallGoods = dao.selectById(id);
        if (ObjectUtil.isNull(pointsMallGoods) || pointsMallGoods.getIsDel()) {
            throw new HhException("未找到对应积分商品信息");
        }
        if (pointsMallGoods.getStatus().equals(0)) {
            throw new HhException("积分商品已下架");
        }
        StoreIntegralDetailResponse productDetailResponse = new StoreIntegralDetailResponse();

        IntegralDetailH5Response detailH5Response = new IntegralDetailH5Response();
        BeanUtils.copyProperties(pointsMallGoods, detailH5Response);
        detailH5Response.setStoreName(pointsMallGoods.getTitle());
        detailH5Response.setSliderImages(StrUtil.split(pointsMallGoods.getImages(), ","));
        detailH5Response.setStoreInfo(pointsMallGoods.getInfo());
        // 详情
        StoreProductDescription sd = storeProductDescriptionService.getOne(
                new LambdaQueryWrapper<StoreProductDescription>()
                        .eq(StoreProductDescription::getProductId, id)
                        .eq(StoreProductDescription::getType, Constants.PRODUCT_TYPE_INTEGRAL));
        if (ObjectUtil.isNotNull(sd)) {
            detailH5Response.setContent(ObjectUtil.isNull(sd.getDescription()) ? "" : sd.getDescription());
        }
        // 获取主商品信息
        StoreProduct storeProduct = storeProductService.getById(pointsMallGoods.getProductId());
        // 主商品状态
        if (storeProduct.getIsDel()) {
            productDetailResponse.setMasterStatus("delete");
        } else if (!storeProduct.getIsShow()) {
            productDetailResponse.setMasterStatus("soldOut");
        } else if (storeProduct.getStock() <= 0) {
            productDetailResponse.setMasterStatus("sellOut");
        } else {
            productDetailResponse.setMasterStatus("normal");
        }

        // 秒杀销量 = 原商品销量（包含虚拟销量）
        detailH5Response.setSales(storeProduct.getSales());
        detailH5Response.setFicti(storeProduct.getFicti());



        productDetailResponse.setStoreIntegral(detailH5Response);

        // 获取秒杀商品规格
        List<StoreProductAttr> attrList = attrService.getListByProductIdAndType(id, Constants.PRODUCT_TYPE_INTEGRAL);
        // 根据制式设置attr属性
        productDetailResponse.setProductAttr(attrList);

        // 根据制式设置sku属性
        HashMap<String, Object> skuMap = MapUtil.newHashMap();
        // 获取主商品sku
        List<StoreProductAttrValue> storeProductAttrValues = storeProductAttrValueService.getListByProductIdAndType(pointsMallGoods.getProductId(), Constants.PRODUCT_TYPE_NORMAL);
        // 获取秒杀商品sku
        List<StoreProductAttrValue> integralAttrValues = storeProductAttrValueService.getListByProductIdAndType(pointsMallGoods.getId(), Constants.PRODUCT_TYPE_INTEGRAL);

        for (int i = 0; i < storeProductAttrValues.size(); i++) {
            IntegralProductAttrValueResponse atr = new IntegralProductAttrValueResponse();
            StoreProductAttrValue productAttrValue = storeProductAttrValues.get(i);
            List<StoreProductAttrValue> valueList = integralAttrValues.stream().filter(e -> productAttrValue.getSuk().equals(e.getSuk())).collect(Collectors.toList());
            if (CollUtil.isEmpty(valueList)) {
                BeanUtils.copyProperties(productAttrValue, atr);
                atr.setPrice(productAttrValue.getPrice().intValue());
            } else {
                BeanUtils.copyProperties(valueList.get(0), atr);
                atr.setPrice(valueList.get(0).getPrice().intValue());
            }

            skuMap.put(atr.getSuk(), atr);
        }
        productDetailResponse.setProductValue(skuMap);
        return productDetailResponse;
    }

    @Override
    public MyRecord exchange(IntegralCreateOrderRequest request) {
        User user = userService.getInfoException();

        Integer userId = user.getUid();
        if (request.getAddressId() <= 0) {
            throw new HhException("请选择收货地址");
        }
        UserAddress userAddress = userAddressService.getById(request.getAddressId());
        if (ObjectUtil.isNull(userAddress) || userAddress.getIsDel()) {
            throw new HhException("收货地址有误");
        }
        if(!user.getUid().equals(userAddress.getUid())){
            throw new HhException("收货地址异常，请重新选择");
        }
        String userAddressStr = userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getDetail();
        // 生成订单号
        String orderNo = HhUtil.getOrderNo();

        MyRecord skuRecordList = validateProductStock(request);


        String createOrderKey = Constants.USER_ASSETS_LOCK + userId;
        RLock redissonLock = this.redissonClient.getLock(createOrderKey);
        //加锁
        redissonLock.lock();
        try {
            UserAssetVo userAsset = userService.getUserAsset(userId);
            StoreProductAttrValue attrValue = skuRecordList.get("attrValue");
            PointsMallGoods storeProduct = skuRecordList.get("storeProduct");
            //计算价格
            IntegralOrderPriceResponse integralOrderPriceResponse = calculatePrice(attrValue,request.getProductNum(),request.getAddressId());

            if(userAsset.getIntegral() < integralOrderPriceResponse.getProTotalFee()){
                throw new HhException("您的积分余额不足！");
            }
            IntegralOrderInfo integralOrderInfo = new IntegralOrderInfo();
            integralOrderInfo.setProductId(attrValue.getProductId());
            integralOrderInfo.setOrderNo(orderNo);
            integralOrderInfo.setUnique(attrValue.getId().toString());
            integralOrderInfo.setProductName(storeProduct.getTitle());
            integralOrderInfo.setAttrValueId(attrValue.getId());
            integralOrderInfo.setImage(storeProduct.getImage());
            integralOrderInfo.setSku(attrValue.getSuk());
            integralOrderInfo.setPrice(attrValue.getPrice().intValue());
            integralOrderInfo.setPayNum(request.getProductNum());
            integralOrderInfo.setWeight(attrValue.getWeight());
            integralOrderInfo.setVolume(attrValue.getVolume());
            integralOrderInfo.setIsReply(false);

            IntegralOrder storeOrder = new IntegralOrder();
            storeOrder.setOrderId(orderNo);
            storeOrder.setUid(userId);
            storeOrder.setMerId(user.getMerId());
            storeOrder.setRealName(userAddress.getRealName());
            storeOrder.setTotalNum(request.getProductNum());
            storeOrder.setUserPhone(userAddress.getPhone());
            storeOrder.setUserAddress(userAddressStr);
            storeOrder.setTotalPrice(BigDecimal.valueOf(integralOrderPriceResponse.getProTotalFee()));
            storeOrder.setPayPrice(integralOrderPriceResponse.getPayFee());
            storeOrder.setProTotalPrice(integralOrderPriceResponse.getProTotalFee());
            storeOrder.setMark(StringEscapeUtils.escapeHtml4(request.getMark()));
            storeOrder.setPaid(true);
            storeOrder.setPayTime(DateUtil.nowDateTime());
            storeOrder.setKeywords(storeProduct.getTitle());
            storeOrder.setCost(attrValue.getCost());
            Boolean execute = transactionTemplate.execute(e->{
                //插入订单记录
                integralOrderService.create(storeOrder);

                integralOrderInfo.setOrderId(storeOrder.getId());
                //插入订单详情记录
                integralOrderInfoService.create(integralOrderInfo);
                //更新用户积分
                userAssetService.updateUserIntegralBalance(userId,integralOrderPriceResponse.getProTotalFee(),"sub", IntegralTransactionType.REDEMPTIONGOODS.getCode(),1,orderNo);
                // 普通商品口库存
                pointsMallGoodsService.operationStock(storeProduct.getId(), request.getProductNum(), "sub");
                // 普通商品规格扣库存
                attrValueService.operationStock(attrValue.getId(), request.getProductNum(), "sub", Constants.PRODUCT_TYPE_INTEGRAL);
                // 生成订单日志
                integralOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_STATUS_CACHE_CREATE_ORDER, "订单生成");

                return Boolean.TRUE;
            });
            if(!execute){
                throw new HhException("兑换失败");
            }
            MyRecord record = new MyRecord();
            record.set("orderNo", storeOrder.getOrderId());
            return record;
        }finally {
            redissonLock.unlock();
        }
    }
    /**
     * 再兑一单
     * @param orderId
     * @return
     */
    @Override
    public MyRecord againExchange(String orderId) {
        IntegralOrder order = integralOrderService.getByOderId(orderId);
        if(ObjectUtil.isNull(order)){
            throw new HhException("订单号错误");
        }

        User user = userService.getInfoException();

        Integer userId = user.getUid();

        if(!order.getUid().equals(userId)){
            throw new HhException("兑换失败");
        }

        List<IntegralOrderInfo> listByOrderNo = integralOrderInfoService.getListByOrderNo(order.getOrderId());

        if(listByOrderNo.size() < 1){
            throw new HhException("兑换失败");
        }

        IntegralOrderInfo integralOrderInfoVo = listByOrderNo.get(0);

        IntegralCreateOrderRequest integralCreateOrderRequest = new IntegralCreateOrderRequest();

        integralCreateOrderRequest.setProductId(integralOrderInfoVo.getProductId());
        integralCreateOrderRequest.setAttrValueId(integralOrderInfoVo.getAttrValueId());
        integralCreateOrderRequest.setProductNum(integralOrderInfoVo.getPayNum());
        MyRecord skuRecordList = validateProductStock(integralCreateOrderRequest);

        // 生成订单号
        String orderNo = HhUtil.getOrderNo();
        String createOrderKey = Constants.USER_ASSETS_LOCK + userId;
        RLock redissonLock = this.redissonClient.getLock(createOrderKey);
        //加锁
        redissonLock.lock();
        try {
            UserAssetVo userAsset = userService.getUserAsset(userId);
            StoreProductAttrValue attrValue = skuRecordList.get("attrValue");
            PointsMallGoods storeProduct = skuRecordList.get("storeProduct");
            //计算价格
            IntegralOrderPriceResponse integralOrderPriceResponse = calculatePrice(attrValue,integralCreateOrderRequest.getProductNum(),integralCreateOrderRequest.getAddressId());

            if(userAsset.getIntegral() < integralOrderPriceResponse.getProTotalFee()){
                throw new HhException("您的积分余额不足！");
            }
            IntegralOrderInfo integralOrderInfo = new IntegralOrderInfo();
            integralOrderInfo.setProductId(attrValue.getProductId());
            integralOrderInfo.setOrderNo(orderNo);
            integralOrderInfo.setUnique(attrValue.getId().toString());
            integralOrderInfo.setProductName(storeProduct.getTitle());
            integralOrderInfo.setAttrValueId(attrValue.getId());
            integralOrderInfo.setImage(storeProduct.getImage());
            integralOrderInfo.setSku(attrValue.getSuk());
            integralOrderInfo.setPrice(attrValue.getPrice().intValue());
            integralOrderInfo.setPayNum(integralCreateOrderRequest.getProductNum());
            integralOrderInfo.setWeight(attrValue.getWeight());
            integralOrderInfo.setVolume(attrValue.getVolume());
            integralOrderInfo.setIsReply(false);

            IntegralOrder storeOrder = new IntegralOrder();
            storeOrder.setOrderId(orderNo);
            storeOrder.setUid(userId);
            storeOrder.setMerId(user.getMerId());
            storeOrder.setRealName(order.getRealName());
            storeOrder.setTotalNum(order.getTotalNum());
            storeOrder.setUserPhone(order.getUserPhone());
            storeOrder.setUserAddress(order.getUserAddress());
            storeOrder.setTotalPrice(BigDecimal.valueOf(integralOrderPriceResponse.getProTotalFee()));
            storeOrder.setPayPrice(integralOrderPriceResponse.getPayFee());
            storeOrder.setProTotalPrice(integralOrderPriceResponse.getProTotalFee());
            storeOrder.setMark(StringEscapeUtils.escapeHtml4(order.getMark()));
            storeOrder.setPaid(true);
            storeOrder.setPayTime(DateUtil.nowDateTime());
            storeOrder.setKeywords(storeProduct.getTitle());
            storeOrder.setCost(attrValue.getCost());
            Boolean execute = transactionTemplate.execute(e->{
                //插入订单记录
                integralOrderService.create(storeOrder);

                integralOrderInfo.setOrderId(storeOrder.getId());
                //插入订单详情记录
                integralOrderInfoService.create(integralOrderInfo);
                //更新用户积分
                userAssetService.updateUserIntegralBalance(userId,integralOrderPriceResponse.getProTotalFee(),"sub", IntegralTransactionType.REDEMPTIONGOODS.getCode(),1,orderNo);
                // 普通商品口库存
                pointsMallGoodsService.operationStock(storeProduct.getId(), integralCreateOrderRequest.getProductNum(), "sub");
                // 普通商品规格扣库存
                attrValueService.operationStock(attrValue.getId(), integralCreateOrderRequest.getProductNum(), "sub", Constants.PRODUCT_TYPE_INTEGRAL);
                // 生成订单日志
                integralOrderStatusService.createLog(storeOrder.getId(), Constants.ORDER_STATUS_CACHE_CREATE_ORDER, "订单生成");

                return Boolean.TRUE;
            });
            if(!execute){
                throw new HhException("兑换失败");
            }
            MyRecord record = new MyRecord();
            record.set("orderNo", storeOrder.getOrderId());
            return record;
        }finally {
            redissonLock.unlock();
        }


    }

    @Override
    public Boolean updateIntegralGoods(StoreIntegralAddRequest request) {
        PointsMallGoods pointsMallGoods = getById(request.getId());
        if (ObjectUtil.isNull(pointsMallGoods) || pointsMallGoods.getIsDel()) {
            throw new HhException("积分商品不存在");
        }

        if (pointsMallGoods.getStatus().equals(1)) {
            throw new HhException("请先关闭积分商品，再修改商品信息");
        }


        PointsMallGoods pmGoods = new PointsMallGoods();
        BeanUtils.copyProperties(request, pmGoods);


        //主图
        pmGoods.setImage(systemAttachmentService.clearPrefix(pmGoods.getImage()));

        //轮播图
        pmGoods.setImages(systemAttachmentService.clearPrefix(pmGoods.getImages()));

        //计算价格
        List<StoreProductAttrValueAddRequest> attrValueAddRequestList = request.getAttrValue();
        StoreProductAttrValueAddRequest minAttrValue = attrValueAddRequestList.stream().min(Comparator.comparing(StoreProductAttrValueAddRequest::getPrice)).get();
        pmGoods.setPrice(minAttrValue.getPrice().intValue());
        pmGoods.setOtPrice(minAttrValue.getOtPrice());
        pmGoods.setCost(minAttrValue.getCost());
        int quota = attrValueAddRequestList.stream().mapToInt(StoreProductAttrValueAddRequest::getQuota).sum();
        pmGoods.setStock(quota);
        pmGoods.setQuota(quota);
        pmGoods.setQuotaShow(quota);

        List<StoreProductAttrAddRequest> addRequestList = request.getAttr();
        List<StoreProductAttr> attrAddList = CollUtil.newArrayList();
        List<StoreProductAttr> attrUpdateList = CollUtil.newArrayList();
        addRequestList.forEach(e -> {
            StoreProductAttr attr = new StoreProductAttr();
            BeanUtils.copyProperties(e, attr);
            if (ObjectUtil.isNull(attr.getId())) {
                attr.setProductId(pmGoods.getId());
                attr.setType(Constants.PRODUCT_TYPE_INTEGRAL);
                attrAddList.add(attr);
            } else {
                attr.setProductId(pmGoods.getId());
                attr.setIsDel(false);
                attrUpdateList.add(attr);
            }
        });

        // attrValue部分
        List<StoreProductAttrValue> attrValueAddList = CollUtil.newArrayList();
        List<StoreProductAttrValue> attrValueUpdateList = CollUtil.newArrayList();
        attrValueAddRequestList.forEach(e -> {
            StoreProductAttrValue attrValue = new StoreProductAttrValue();
            BeanUtils.copyProperties(e, attrValue);
            attrValue.setSuk(e.getSuk());
            attrValue.setImage(systemAttachmentService.clearPrefix(e.getImage()));
            if (ObjectUtil.isNull(attrValue.getId())) {
                attrValue.setProductId(pmGoods.getId());
                attrValue.setQuota(e.getQuota());
                attrValue.setQuotaShow(e.getQuota());
                attrValue.setType(Constants.PRODUCT_TYPE_INTEGRAL);
                attrValueAddList.add(attrValue);
            } else {
                attrValue.setProductId(pmGoods.getId());
                attrValue.setIsDel(false);
                attrValueUpdateList.add(attrValue);
            }
        });

        // 处理富文本
        StoreProductDescription spd = new StoreProductDescription();
        spd.setDescription(request.getContent().length() > 0 ? systemAttachmentService.clearPrefix(request.getContent()) : "");
        spd.setType(Constants.PRODUCT_TYPE_INTEGRAL);
        spd.setProductId(pmGoods.getId());

        Boolean execute = transactionTemplate.execute(e -> {
            dao.updateById(pmGoods);

            // 先删除原用attr+value
            attrService.deleteByProductIdAndType(pmGoods.getId(), Constants.PRODUCT_TYPE_INTEGRAL);
            storeProductAttrValueService.deleteByProductIdAndType(pmGoods.getId(), Constants.PRODUCT_TYPE_INTEGRAL);

            if (CollUtil.isNotEmpty(attrAddList)) {
                attrService.saveBatch(attrAddList);
            }
            if (CollUtil.isNotEmpty(attrUpdateList)) {
                attrService.saveOrUpdateBatch(attrUpdateList);
            }

            if (CollUtil.isNotEmpty(attrValueAddList)) {
                storeProductAttrValueService.saveBatch(attrValueAddList);
            }
            if (CollUtil.isNotEmpty(attrValueUpdateList)) {
                storeProductAttrValueService.saveOrUpdateBatch(attrValueUpdateList);
            }

            storeProductDescriptionService.deleteByProductId(pmGoods.getId(), Constants.PRODUCT_TYPE_INTEGRAL);
            storeProductDescriptionService.save(spd);

            return Boolean.TRUE;
        });
        return execute;
    }

    @Override
    public IntegralProductInfoResponse getDetailAdmin(Integer integralId) {
        PointsMallGoods pointsMallGoods = dao.selectById(integralId);
        if (ObjectUtil.isNull(pointsMallGoods) || pointsMallGoods.getIsDel()) {
            throw new HhException("未找到对应商品信息");
        }
        IntegralProductInfoResponse infoResponse = new IntegralProductInfoResponse();
        BeanUtils.copyProperties(pointsMallGoods, infoResponse);

        infoResponse.setStoreName(pointsMallGoods.getTitle());
        infoResponse.setStoreInfo(pointsMallGoods.getInfo());
        infoResponse.setSliderImage(String.join(",",pointsMallGoods.getImages()));
        infoResponse.setProductId(pointsMallGoods.getProductId());

        // 查询attr
        List<StoreProductAttr> attrList = attrService.getListByProductIdAndType(integralId, Constants.PRODUCT_TYPE_INTEGRAL);
        infoResponse.setAttr(attrList);

        // 注意：数据瓶装步骤：分别查询秒杀和商品本山信息组装sku信息之后，再对比sku属性是否相等来赋值是否秒杀sku信息
        List<StoreProductAttrValue> seckillAttrValueList = storeProductAttrValueService.getListByProductIdAndType(integralId, Constants.PRODUCT_TYPE_INTEGRAL);
        // 查询主商品sku
        List<StoreProductAttrValue> attrValueList = storeProductAttrValueService.getListByProductIdAndType(pointsMallGoods.getProductId(), Constants.PRODUCT_TYPE_NORMAL);

        List<AttrValueResponse> valueResponseList = attrValueList.stream().map(e -> {
            AttrValueResponse valueResponse = new AttrValueResponse();
            Integer id = 0;
            for (StoreProductAttrValue value : seckillAttrValueList) {
                if (value.getSuk().equals(e.getSuk())) {
                    id = value.getId();
                    BeanUtils.copyProperties(value, valueResponse);
                    break;
                }
            }
            if (id.equals(0)) {
                BeanUtils.copyProperties(e, valueResponse);
                valueResponse.setId(null);
            } else {
                valueResponse.setId(id);
            }
            return valueResponse;
        }).collect(Collectors.toList());
        infoResponse.setAttrValue(valueResponseList);

        StoreProductDescription sd = storeProductDescriptionService.getByProductIdAndType(integralId, Constants.PRODUCT_TYPE_INTEGRAL);
        if (ObjectUtil.isNotNull(sd)) {
            infoResponse.setContent(ObjectUtil.isNull(sd.getDescription()) ? "" : sd.getDescription());
        }
        return infoResponse;
    }

    @Override
    public Boolean updateIntegralGoodsStatus(Integer integralId, boolean status) {
        PointsMallGoods pmGoods = getById(integralId);
        if (ObjectUtil.isNull(pmGoods) || pmGoods.getIsDel()) {
            throw new HhException("积分商品不存在");
        }
        if (status) {
            // 判断商品是否存在
            StoreProduct product = storeProductService.getById(pmGoods.getProductId());
            if (ObjectUtil.isNull(product)) {
                throw new HhException("关联的商品已删除，无法开启活动");
            }
        }

        PointsMallGoods storeIntegral = new PointsMallGoods().setId(integralId).setStatus(status?1:0);
        return dao.updateById(storeIntegral) > 0;
    }

    private IntegralOrderPriceResponse calculatePrice(StoreProductAttrValue attrValue, Integer productNum, Integer addressId) {
        IntegralOrderPriceResponse integralOrderPriceResponse = new IntegralOrderPriceResponse();
        BigDecimal num = BigDecimal.valueOf(productNum);
        BigDecimal price = attrValue.getPrice();
        BigDecimal proTotalFee = price.multiply(num);
        integralOrderPriceResponse.setProTotalFee(proTotalFee.intValue());
        BigDecimal freightFee = getFreightFee(attrValue,addressId,productNum);
        BigDecimal payFee = proTotalFee.add(freightFee);
        integralOrderPriceResponse.setFreightFee(freightFee);
        integralOrderPriceResponse.setPayFee(payFee);
        return integralOrderPriceResponse;
    }

    /**
     * 计算运费
     * @param attrValue
     * @param addressId
     * @param productNum
     * @return
     */
    private BigDecimal getFreightFee(StoreProductAttrValue attrValue, Integer addressId, Integer productNum) {
        return BigDecimal.ZERO;
    }


    /**
     * 校验商品库存（生成订单）
     *
     * @param request 订单详情
     * @return List<MyRecord>
     * skuRecord 扣减库存对象
     * ——activityId             活动商品id
     * ——activityAttrValueId    活动商品skuId
     * ——productId              普通（主）商品id
     * ——attrValueId            普通（主）商品skuId
     * ——num                    购买数量
     */
    private MyRecord validateProductStock(IntegralCreateOrderRequest request) {

        // 普通商品
        PointsMallGoods storeProduct = this.pointsMallGoodsService.getById(request.getProductId());

        if (ObjectUtil.isNull(storeProduct)) {
            throw new HhException("购买的商品信息不存在");
        }
        if (storeProduct.getIsDel()) {
            throw new HhException("购买的商品已删除");
        }
        if (!storeProduct.getIsShow()) {
            throw new HhException("购买的商品已下架");
        }
        if (storeProduct.getStock().equals(0) || request.getProductNum() > storeProduct.getStock()) {
            throw new HhException("购买的商品库存不足");
        }

        // 查询商品规格属性值信息
        StoreProductAttrValue attrValue = this.attrValueService.getByIdAndProductIdAndType(
                request.getAttrValueId(), request.getProductId(), Constants.PRODUCT_TYPE_INTEGRAL);
        if (ObjectUtil.isNull(attrValue)) {
            throw new HhException("购买的商品规格信息不存在");
        }
        if (attrValue.getStock() < request.getProductNum()) {
            throw new HhException("购买的商品库存不足");
        }
        MyRecord record = new MyRecord();
        record.set("storeProduct", storeProduct);
        record.set("attrValue", attrValue);
        return record;
    }


    // 是否存在秒杀活动标题查找
    private Boolean isExistTile(String title) {
        LambdaQueryWrapper<PointsMallGoods> lqw = Wrappers.lambdaQuery();
        lqw.select(PointsMallGoods::getId);
        lqw.eq(PointsMallGoods::getTitle, title);
        lqw.eq(PointsMallGoods::getIsDel, false);
        PointsMallGoods pointsMallGoods = dao.selectOne(lqw);
        return ObjectUtil.isNotNull(pointsMallGoods);
    }
}
